# -*- coding: utf-8 -*-
"""
__mktime__ = '2019/4/14'
__author__ = 'Just'
__filename__ = 'user'
"""
from sqlalchemy import Column, Integer, String, SmallInteger, orm
from werkzeug.security import generate_password_hash, check_password_hash
from app.libs.enums import ScopeTypeEnum
from app.libs.error_code import NotFoundException, AuthFailedException
from app.model.base import BaseModel, db
from app.services.clientservice import ClientService


# 用户与漫画关联表 多对多 user <- user_manhua -> manhua
user_comic = db.Table(
    'user_comic',
    db.Column('id', db.Integer, primary_key=True, autoincrement=True),
    db.Column('uid', db.Integer, db.ForeignKey('user.id')),
    db.Column('cid', db.Integer, db.ForeignKey('comic.cid'))
)


class User(BaseModel):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True, autoincrement=True)
    account = Column(String(24), unique=True, nullable=False, comment='账号')
    nickname = Column(String(24), default='未设置', comment='昵称')
    auth = Column(SmallInteger, default=1, comment='权限 默认普通用户:1')
    _password = Column('password', String(100), comment='密码 sha256加密 password字段长度置大于 94 !')
    type = Column(SmallInteger, default=100, comment='客户端类型 [100:邮箱 101:手机号码 200:微信小程序 201:微信公众号]')

    # 多对多 我的漫画
    comics = db.relationship('Comic', secondary=user_comic, backref=db.backref('users', lazy='dynamic'), lazy='dynamic')
    # 一对多 我的阅读记录
    records = db.relationship('ReadRecord',  backref='read_record', lazy='dynamic')

    @orm.reconstructor
    def __init__(self):
        # 序列化列表
        self.fields = ['id', 'account', 'nickname', 'auth', 'type']

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, raw):
        self._password = generate_password_hash(raw)

    def check_password(self, raw):
        """密码校验"""
        if not self._password:
            return False
        return check_password_hash(self._password, raw)

    @staticmethod
    def verify_login_by_email(email, password):
        """邮箱账号登录"""
        user = User.query.filter_by(account=email).first()
        if not user:
            raise NotFoundException(msg='用户不存在', error_code=6001)
        if not user.check_password(password):
            raise AuthFailedException(msg='账号或密码错误', error_code=6003)
        scope = ScopeTypeEnum(user.auth).name
        return {'uid': user.id, 'scope': scope}

    @staticmethod
    def verify_login_by_mina(code, password):
        """小程序登录"""
        client = ClientService()
        client.get_mina_by_code(code)
        openid = client.wx_data['openid']
        user = User.query.filter(User.account == openid).first()
        if not user:
            raise NotFoundException()
        scope = ScopeTypeEnum(user.auth).name
        return {'uid': user.id, 'scope': scope}

    @staticmethod
    def register_by_email(nickname, account, password, type):
        """邮箱注册"""
        with db.auto_commit():
            user = User()
            user.nickname = nickname
            user.account = account
            user.password = password
            user.type = type
            db.session.add(user)

    @staticmethod
    def register_by_mani(account, type):
        """微信小程序注册"""
        with db.auto_commit():
            user = User()
            user.account = account
            user.type = type
            db.session.add(user)
